package cn.datawin.cotask;

import cn.datawin.spider.httputil.HttpRequest.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.DefaultHttpClient;

import com.mongodb.BasicDBObject;

import sun.misc.BASE64Encoder;

import cn.datawin.cotask.bo.CoTask;
import cn.datawin.cotask.bo.CoTaskResult;
import cn.datawin.cotask.client.ClientPool;
import cn.datawin.cotask.util.CoTaskUtil;
import cn.datawin.spider.httputil.HttpRequest;
import cn.datawin.spider.httputil.HttpResponse;
import cn.datawin.spider.httputil.HttpService;
import cn.datawin.spider.seletor.Html;
import cn.datawin.spider.util.UrlUtil;
import cn.datawin.task.dao.DbUtil;
import cn.datawin.task.util.HtmlImg;
import cn.datawin.task.util.HttpUtil;
import cn.datawin.task.util.SpiderUtil;

public class CoPage {
	
	static BASE64Encoder encoder = new BASE64Encoder();
	
	private CoTask task;
	
	private CoTaskResult result = new CoTaskResult();
	
	private Map<String, Object> paramsResults = new HashMap<String, Object>();
	
	private HttpService httpService ;
	
	private HttpRequest httpRequest;
	
	private HttpResponse httpResponse;
	
	private Html html;
	
	public void exec() throws Exception{
		/*解析task 转化*/
		task2this();
		httpResponse = httpService.execute(httpRequest);
		String res =  httpResponse.getResponseString();
		System.out.println("result::::::::"+ (res.length()>500? res.substring(0,500):res));
		html  = new Html(res);
		
		/* 执行 rule*/
		getTesult();
		
		/*根据method 操作数据插入 还是 nexttask*/
		branch();
	}
	
	
	public CoPage(CoTask task ) {
		this.task = task;
	}
	
	public void task2this(){
		this.httpService = ClientPool.get(task.getClientid());
		httpRequest = new HttpRequest(task.getUrl());
		httpRequest.setCharset(task.getCharset());
		httpRequest.setCookies(task.getCookie());
		httpRequest.setConnectTimeout(6000);
		httpRequest.setReadTimeout(6000);
		httpRequest.setMethod(task.getMethod().equalsIgnoreCase("post") ? Method.post : Method.get);
		httpRequest.setHeaders(task.getHeader());
		httpRequest.setPostParams(task.getData());
	}
	
	public void getTesult() throws Exception{
		parseCookieByRule();
		parseCaptchaByRule();
		parseHtmlByRule();
		
		result.setClientid(task.getClientid());
		result.setSig(task.getSig());
		result.setTaskid(task.getId());
		result.setType(task.getType());
		result.setWorkbeach(task.getWorkbeach());
		
		/* 修改 task 状态 结束*/
		CoTaskUtil.updateCoTask(task.getId(), "1");
	}
	
	
	public void parseCookieByRule(){
		List<Map<String, Object>> expression = task.getRules();
		if(expression == null) return;
		
		List<Map<String, Object>> remove = new ArrayList<Map<String,Object>>();
		for (Map<String, Object> map : expression) {
			if(!map.containsKey("cookie")){
				continue;
			}
			remove.add(map);
			String key =  (String)map.get("cookie");
			String cookie =  httpResponse.getCookies().get(key);
			paramsResults.put((String)map.get("name"), cookie);
		}
		expression.removeAll(remove);
	}
	
	
	public void parseCaptchaByRule(){
		List<Map<String, Object>> expression = task.getRules();
		if(expression == null) return;
		
		List<Map<String, Object>> remove = new ArrayList<Map<String,Object>>();
		for (Map<String, Object> map : expression) {
			if(!map.containsKey("captcha")){
				continue;
			}
			remove.add(map);
			paramsResults.put((String)map.get("name"), encoder.encode(httpResponse.getResponseData()));
		}
		expression.removeAll(remove);
	}
	
	
	public void parseHtmlByRule(){
		List<Map<String, Object>> expression = task.getRules();
		if(expression == null) return;
		for (Map<String, Object> map : expression) {
			/*添加 ImgCut 功能*/
			HtmlImg Imghtml = new HtmlImg();
			Imghtml.setUrl(this.getHttpRequest().getUrl());
			 /* 用于执行 js 的判断 */
			if(Boolean.valueOf((String)map.remove("execjs"))){ 
				List<Cookie> cookies =  ((DefaultHttpClient)getHttpService()).getCookieStore().getCookies();
				Imghtml.execjs(cookies);
			}else{
				Imghtml.setElements(html.getElements());
			}
			
			String n = (String)map.remove("name");
			Set<String> sets = map.keySet();
			Iterator<String> ite = sets.iterator();
			while (ite.hasNext()) {
				String type = ite.next();
				String value = (String)map.get(type);
				java.lang.reflect.Method me = SpiderUtil.getHtmlMethod(type);
				Object result = null;
				if(StringUtils.isEmpty(value)){
					result = SpiderUtil.invokeMethod(me, Imghtml);
				}else{
					result = SpiderUtil.invokeMethod(me, Imghtml, value);
				}
				if (!ite.hasNext()) {
					if(result == null || result.toString().isEmpty()){
						continue;
					}
					paramsResults.put(n, result);
				}
			}
		}
		result.setResult(paramsResults);
	}
	
	
	private void branch() throws Exception{
		String sig  = task.getSig();
		if(sig.startsWith("$data")){
			 /* 做数据存储*/
			DbUtil.getcoll(task.getType()+"data").insert(new BasicDBObject(result.getResult()));
		}
		/* 返回 taskResult*/
		Map<String, String> coTaskResult = new HashMap<String, String>();
		coTaskResult.put("coTaskResult", HttpUtil.serialize(result.toMap()));
		CoTaskUtil.insertCoTaskResult(coTaskResult);
	}
	
	public HttpService getHttpService() {
		return httpService;
	}

	public void setHttpService(HttpService httpService) {
		this.httpService = httpService;
	}

	public HttpRequest getHttpRequest() {
		return httpRequest;
	}

	public void setHttpRequest(HttpRequest httpRequest) {
		this.httpRequest = httpRequest;
	}

	public HttpResponse getHttpResponse() {
		return httpResponse;
	}

	public void setHttpResponse(HttpResponse httpResponse) {
		this.httpResponse = httpResponse;
	}

	public Html getHtml() {
		return html;
	}

	public void setHtml(Html html) {
		this.html = html;
	}

	public String getHost(){
		return UrlUtil.getHost(httpRequest.getUrl());
	}
	
	public String getUri(){
		return UrlUtil.getUri(httpRequest.getUrl());
	}
	
	public String getDoman(){
		return UrlUtil.getDomain(httpRequest.getUrl());
	}

}
